package service

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"time"

	"sigs.k8s.io/yaml"
)

// UpgradeService
type UpgradeService struct {
	Version    string
	Repository string
	TempFile   string
}

func NewUpgradeService() *UpgradeService {
	u := &UpgradeService{}
	u.Version = "v1.0.1"
	u.Repository = "https://gitee.com/toy-kit/robot-arm"
	return u
}
func (u *UpgradeService) Check() string {
	latest, err := u.getLatestVersion()
	if err != nil {
		return ""
	}
	return latest
}
func (u *UpgradeService) Download(latest string) (string, error) {
	res, err := http.Get(fmt.Sprintf("%v/releases/download/%v/RobotArm.exe", u.Repository, latest))
	if err != nil {
		return "", err
	}
	exePath, err := os.Executable()
	if err != nil {
		return "", err
	}
	fileName := path.Join(filepath.Dir(exePath), fmt.Sprintf("%v%v", latest, filepath.Ext(exePath)))
	file, err := os.Create(fileName)
	if err != nil {
		return "", err
	}
	_, wErr := io.Copy(file, res.Body)
	if wErr != nil {
		return "", wErr
	}
	defer res.Body.Close()
	defer file.Close()
	return fileName, nil
}
func (u *UpgradeService) Install(appPath string) error {
	exePath, err := os.Executable()
	if err != nil {
		return err
	}
	return exec.Command(appPath, "upgrade", exePath).Start()
}

func Upgrade(appPath string) error {
	exePath, err := os.Executable()
	if err != nil {
		return err
	}
	f, err := os.ReadFile(exePath)
	if err != nil {
		return err
	}
	if err := os.WriteFile(appPath, f, 0755); err != nil {
		return err
	}
	go func() {
		time.Sleep(time.Second * 1)
		os.Remove(exePath)
		os.Exit(0)
	}()
	return exec.Command(appPath).Start()
}

func (u *UpgradeService) getLatestVersion() (string, error) {
	resp, err := http.Get(fmt.Sprintf("%s/raw/master/Taskfile.yml", u.Repository))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	type Vars struct {
		Version string `json:"VERSION"`
	}
	type BuildConfig struct {
		Vars Vars `json:"vars"`
	}
	var buildConfig BuildConfig
	if err := yaml.Unmarshal(body, &buildConfig); err != nil {
		return "", err
	}
	return buildConfig.Vars.Version, nil
}
